
/**
 * @fileoverview This class represents a single binding from one event to
 * multiple templates.
 * @author johannes.nel@gmail.com (JOhan)
 * Date: 2012/02/26
 * Time: 10:03 AM
 */
goog.provide('lfpug.binding.Binding');
goog.require('goog.Disposable');



/**
 * @constructor
 * @extends {goog.Disposable}
 *
 * @param {lfpug.ui.Component} component The component on which this binding
 *  is active.
 * @param {string} event  The events.
 * @param {Function} template The templates.
 * @param {string} elementResolver The function which resolves the element
 * being replaced.
 * @param {Function} templateObjFunc The function which builds the template
 * object.
 * @param {Object} scope The scope which the template object function should
 * be called.
 * @param {Array=} opt_args Any arguments you wish to pass to the
 * templateObjFunc.
 * @param {Array.<Function>=} opt_triggers The triggers I want fired when this
 *  binding has executed.
 */
lfpug.binding.Binding =
    function(component, event, template, elementResolver,
             templateObjFunc, scope, opt_args, opt_triggers) {
  this.args_ = opt_args;
  this.component_ = component;
  this.event_ = event;
  this.template_ = template;
  this.templateObjFunc_ = templateObjFunc;
  this.templateObjFuncScope_ = scope;
  this.elementReslover_ = elementResolver;
  this.triggers_ = opt_triggers;
};
goog.inherits(
    lfpug.binding.Binding,
    goog.Disposable
);


/**
 * Determines if the event passed in should trigger the redraw of this
 * component.
 * @param {string} name The binding name.
 *
 * @return {boolean} Indicates if this binding matches.
 */
lfpug.binding.Binding.prototype.shouldExecute = function(name) {
  if (name == '' || name == this.event_) {
    return true;
  }
  return false;
};


/**
 * The execute function.
 * @param {lfpug.model.BaseModel.ChangedProperty} changedProp The property
 *    triggering the binding.
 */
lfpug.binding.Binding.prototype.execute = function(changedProp) {
  var element = this.component_.getElement();
  var domHelper = this.component_.getDomHelper();
  var obj;
  if (goog.isDefAndNotNull(this.args_)) {
    var args = this.args_;
    if (!goog.isArray(args)) {
      args = [args];
    }
    obj = this.templateObjFunc_.apply(this.templateObjFuncScope_, args);
  } else {
    obj = this.templateObjFunc_.apply(this.templateObjFuncScope_);
  }
  if (goog.isDefAndNotNull(this.elementReslover_) &&
      goog.isString(this.elementReslover_) &&
      goog.string.trim(this.elementReslover_).length > 0) {
    var oldNode = domHelper.getElementByClass(this.elementReslover_, element);
    if (!goog.isDefAndNotNull(oldNode)) {
      oldNode = domHelper.getElement(this.elementReslover_);

    }
    if (!goog.isDefAndNotNull(oldNode)) {
      return;
    }
    var newNode = domHelper.htmlToDocumentFragment(this.template_(obj));
    domHelper.replaceNode(newNode, oldNode);
  } else {
    //replace the whole template
    var newNode = domHelper.htmlToDocumentFragment(this.template_(obj));
    //in this case we need to reset the element on the component
    domHelper.replaceNode(newNode, element);
    this.component_.setElementInternal(/**@type {Element}*/(newNode));
  }
  if (goog.isDefAndNotNull(this.triggers_) && goog.isArray(this.triggers_)) {
    for (var i = 0, l = this.triggers_.length; i < l; i++) {
      this.triggers_[i].apply(this.component_, [changedProp]);
    }
  }
};


/**
 * @override
 */
lfpug.binding.Binding.prototype.disposeInternal = function() {
  goog.base(this, 'disposeInternal');
  delete this.component_;
  delete this.event_;
  delete this.template_;
  delete this.templateObjFunc_;
  delete this.templateObjFuncScope_;
  delete this.elementReslover_;
  delete this.triggers_;
};



